﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Sharpsoft.Controls
{
    public class WrapPanel : Panel
    {

        #region Orientation

        /// <summary> 
        /// Gets or sets the Orientation possible Value of the Orientation object.
        /// </summary> 
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        /// <summary> 
        /// Identifies the Orientation dependency property.
        /// </summary> 
        public static readonly DependencyProperty OrientationProperty =
                    DependencyProperty.Register(
                          "Orientation",
                          typeof(Orientation),
                          typeof(WrapPanel),
                          null);

        #endregion Orientation

        #region AllowAutosizing

        /// <summary> 
        /// Gets or sets the AllowAutosizing possible Value of the bool object.
        /// </summary> 
        public bool AllowAutosizing
        {
            get { return (bool)GetValue(AllowAutosizingProperty); }
            set { SetValue(AllowAutosizingProperty, value); }
        }

        /// <summary> 
        /// Identifies the AllowAutosizing dependency property.
        /// </summary> 
        public static readonly DependencyProperty AllowAutosizingProperty =
                    DependencyProperty.Register(
                          "AllowAutosizing",
                          typeof(bool),
                          typeof(WrapPanel),
                          null);
        #endregion AllowAutosizing

        #region ctor
        public WrapPanel()
        {
            Orientation = Orientation.Horizontal;
        }

        #endregion ctor

        #region overrides
        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement child in Children)
            {
                child.Measure(new Size(availableSize.Width, availableSize.Height));
            }

            return base.MeasureOverride(availableSize);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {

            Point point = new Point(0, 0);
            double maxVal = 0;
            int i = 0;

            if (Orientation == Orientation.Horizontal)
            {
                double largestHeight = 0.0;

                foreach (UIElement child in Children)
                {

                    child.Arrange(new Rect(point, new Point(point.X + child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));


                    if (child.DesiredSize.Height > largestHeight)
                        largestHeight = child.DesiredSize.Height;

                    point.X = point.X + child.DesiredSize.Width;

                    if ((i + 1) < Children.Count)
                    {
                        if ((point.X + Children[i + 1].DesiredSize.Width) > finalSize.Width)
                        {
                            point.X = 0;
                            point.Y = point.Y + largestHeight;
                            maxVal += largestHeight;
                            largestHeight = 0.0;
                        }
                    }

                    i++;



                }
                if (AllowAutosizing)
                {
                    finalSize.Height = maxVal;

                    //this is ugly workaround, 'cos ScrollViewer uses Height property instead of ActualHeight
                    if (this.Height != maxVal)
                        SetValue(HeightProperty, maxVal);
                }
            }
            else
            {
                double largestWidth = 0.0;

                foreach (UIElement child in Children)
                {
                    child.Arrange(new Rect(point, new Point(point.X + child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));

                    if (child.DesiredSize.Width > largestWidth)
                        largestWidth = child.DesiredSize.Width;

                    point.Y = point.Y + child.DesiredSize.Height;

                    if ((i + 1) < Children.Count)
                    {
                        if ((point.Y + Children[i + 1].DesiredSize.Height) > finalSize.Height)
                        {
                            point.Y = 0;
                            point.X = point.X + largestWidth;
                            maxVal += largestWidth;
                            largestWidth = 0.0;
                        }
                    }

                    i++;
                }
                if (AllowAutosizing)
                {
                    finalSize.Width = maxVal;

                    //this is ugly workaround, 'cos ScrollViewer uses Width property instead of ActualWidth
                    if (this.Width != maxVal)
                        SetValue(WidthProperty, maxVal);
                }
            }

            return base.ArrangeOverride(finalSize);
        }

        #endregion overrides
    }
}
